# This Python file uses the following encoding: utf-8
import sys
from PySide2.QtWidgets import QApplication, QWidget
from PySide2.QtCore import QTimer, Qt  # 定时器 / 设置窗口样式-无标题栏
from PySide2.QtGui import QPalette, QColor  # 设置窗口颜色
from random import randrange  # random 模块用来生成随机数

colorDict = {7: QColor(125, 125, 125),  # 蛇头用灰色
             0: QColor(255, 0, 0),  # 0-6 分别表示红橙黄绿蓝靛紫
             1: QColor(255, 125, 0),
             2: QColor(255, 255, 0),
             3: QColor(0, 255, 0),
             4: QColor(0, 0, 255),
             5: QColor(0, 255, 255),
             6: QColor(255, 0, 255)}


class SnakeNode(QWidget):
    def __init__(self, sizeX, sizeY, posX, posY, isHead, colorId = 0, Dirction='Right'):
        # 初始化蛇节点的长宽,位置,是否蛇头,颜色,行进方向
        QWidget.__init__(self)
        self.posX = posX
        self.posY = posY
        self.move(posX, posY)
        self.resize(sizeX, sizeY)
        self.setWindowFlag(Qt.FramelessWindowHint)  # 无标题栏
        self.dirction = Dirction
        self.isHead = isHead
        if isHead:
            self.grabKeyboard()  # 蛇头根据键盘输入控制方向
        self.setAutoFillBackground(True)
        palette = QPalette()
        palette.setColor(QPalette.Background, colorDict[colorId])
        self.setPalette(palette)  # 设置窗口颜色
        self.show()

    def keyPressEvent(self, QKeyEvent):  # 键盘事件槽(函数)
        if self.isHead:
            if self.dirction != "Down" and QKeyEvent.key() == Qt.Key_Up:  # 不能直接反向调头
                self.dirction = 'Up'
            elif self.dirction != "Right" and QKeyEvent.key() == Qt.Key_Left:
                self.dirction = 'Left'
            elif self.dirction != "Up" and QKeyEvent.key() == Qt.Key_Down:
                self.dirction = 'Down'
            elif self.dirction != "Left" and QKeyEvent.key() == Qt.Key_Right:
                self.dirction = 'Right'

    def MoveToNext(self):  # 移动一步
        if self.dirction == 'Up':
            self.posY = self.posY - 50
        elif self.dirction == 'Left':
            self.posX = self.posX - 50
        elif self.dirction == 'Down':
            self.posY = self.posY + 50
        elif self.dirction == 'Right':
            self.posX = self.posX + 50
        self.move(self.posX, self.posY)


if __name__ == "__main__":

    def new_food():  # 生成食物
        posTop = randrange(50, screen_height-50, 50)  # 随机生成位置(食物不放边缘上)
        posLeft = randrange(50, screen_width-50, 50)
        global food, fakeFood, colorIdNow
        colorIdNow = (colorIdNow+1) % 7  # 七彩色交替显示
        food = SnakeNode(50, 50, posLeft, posTop, False, colorIdNow)  # 食物
        if fakeFood is not None:
            fakeFood.destroy()
        posTop2 = posTop
        posLeft2 = posLeft
        while posTop2 == posTop and posLeft2 == posLeft:  # 随机另一个位置
            posTop2 = randrange(50, screen_height-50, 50)
            posLeft2 = randrange(50, screen_width-50, 50)
        colorIdTmp = (colorIdNow + randrange(1, 6)) % 7  # 随机生成另一种颜色
        fakeFood = SnakeNode(50, 50, posLeft2, posTop2, False, colorIdTmp)  # 假食物

    def isDead():  # 判断蛇是否死了
        if snake[0].posX < 0 or snake[0].posX > screen_width:  # 撞墙 左右
            return True
        if snake[0].posY < 0 or snake[0].posY > screen_height:  # 撞墙 上下
            return True
        if snake[0].posX == fakeFood.posX and snake[0].posY == fakeFood.posY:  # 吃到假食物
            return True
        for i in range(1, len(snake)):  # 撞到自己
            if snake[0].posX == snake[i].posX and snake[0].posY == snake[i].posY:
                print(snake[0].posX, snake[0].posY)
                return True
        return False

    def updata():  # 更新一次界面(蛇走一步)
        Last_dirct = None
        nposX = snake[-1].posX  # 记录一下蛇最后一个节点信息
        nposY = snake[-1].posY
        nDirct = snake[-1].dirction
        for node in snake:  # 每个节点按自己的方向走一步
            node.MoveToNext()
            if Last_dirct is None:
                Last_dirct = node.dirction
            else:
                Last_dirct, node.dirction = node.dirction, Last_dirct
                # 走完一步后,节点的方向变成了原上一个节点(靠近头)的方向
        print(f"Head: {snake[0].posX}, {snake[0].posY}, Food: {food.posX}, {food.posY}")
        if isDead():  # 死亡则游戏结束
            sys.exit(app.exec_())
        if snake[0].posX == food.posX and snake[0].posY == food.posY:  # 吃到食物
            food.destroy()
            snake.append(SnakeNode(50, 50, nposX, nposY, False, colorIdNow, nDirct))
            # 蛇新增一个节点到蛇尾
            new_food()  # 更新食物信息

    app = QApplication([])
    desktop = app.desktop()
    screen_height = desktop.height()
    screen_width = desktop.width()  # 获取桌面大小,如有问题,可手动改为常数
    print(f"desktop size ({screen_height} , {screen_width})")
    snake = [SnakeNode(50, 50, 200, 100, True, 7),SnakeNode(50, 50, 150, 100, False, 0),SnakeNode(50, 50, 100, 100, False, 1)]
    # 初始化蛇身
    colorIdNow = 1  # 记录新食物的颜色id
    food = None  # 食物
    fakeFood = None  # 颜色不正确的假食物
    new_food()  # 初始化食物
    timer = QTimer()
    timer.timeout.connect(updata)  # 设置定时器
    timer.start(100)  # 设置刷新时间ms(蛇的速度)
    sys.exit(app.exec_())
